package qgs.zisu.javaconcurrency.javaconcurrency.chapter7_synchronized;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/10 8:52
 * @Version 1.0
 */
public class SynchronizedRunnable implements Runnable {
    // 问题：在多线程情况下 对共享数据的修改会有一个问题（存在超额消费）（就是线程不安全问题）
    // index是既要去读 也要去修改。
    private int index = 0;

    // MAX应该是只读 数据。
    private final static int MAX = 500;
    // 很多线程访问的 变量 是同一份，那么这个变量存在线程安全的问题。
    // 如果线程资源不同步的话，那么很可能 输出的号码会超过500，也就是说会超额消费。
    // （造成上诉原因是因为cpu的上下文切换导致一个线程执行到一半不执行了，另外一个线程开始执行）

    //解决方式： 同步代码块的方式
    private final Object MONITOR = new Object();


    // synchronized方法 锁就是 this（SynchronizedRunnable 的实例。）
    // 如果在run 方法上加入 synchronized 就会只让一个线程执行。因为由第一个线程过来执行完，MAX 就已近达到最大值了，其他线程就执行不了了。
    @Override
    public void run() {
        // synchronized(){} 就相当于一个栅栏，当多线程执行到这里后 ，要执行synchronized里面代码就变成了串行，一次只能由一个线程执行

        while (true){
            if (ticket()){
                break;
            }
        }
    }

    // index 是共享数据，是线程安全 至关重要的因素。
    private synchronized boolean ticket(){
        //1.getField
        if(index > MAX){
            return true;
        }
        try {
            Thread.sleep(5);
        }catch (Exception e){
            e.printStackTrace();
        }
        //2. index++
        //3.
        System.out.println(Thread.currentThread()+" 的号码是："+(index++));
        return false;
    }
}
